Skip to content

[Feature] Group nesting "folders" & Profile tree view#10788

Open
D3VL-Jack wants to merge 13 commits intoEugeny:masterfrom
D3VL-Jack:feature-profile-tree-view
Open

[Feature] Group nesting "folders" & Profile tree view#10788
D3VL-Jack wants to merge 13 commits intoEugeny:masterfrom
D3VL-Jack:feature-profile-tree-view

Conversation

@D3VL-Jack
Copy link
Copy Markdown

@D3VL-Jack D3VL-Jack commented Oct 8, 2025

This pull requests adds a tree view profile picker to the main window.
image
Click groups to expand and collapse them, double click profiles to open as a new tab.

Hover actions & context menu options are also available
image image

To achieve this, groups have been given the ability to be nested under another group
image

Care has been taken to ensure backwards compatibility with previous configs.
parentGroupId, icon, color fields have been added to the groups configuration items

groups:
  - id: 62c453d2-01d0-47e1-8723-1eec6373323e
    name: Group 1
    icon: fas fa-layer-group
    color: '#e294ff'
  - id: 7398c52c-2381-4f42-a8b3-816d8b5930e4
    name: Group 2
    icon: fas fa-4
    color: '#ffe33e'
    parentGroupId: 62c453d2-01d0-47e1-8723-1eec6373323e
  - id: f667f830-03af-48c9-b1b8-cfee8bfa84ac
    name: Group 3
    icon: fas fa-boxes-stacked
    color: '#4800f0'
    parentGroupId: f667f830-03af-48c9-b1b8-cfee8bfa84ac

An additional setting has been added to the window tab that allows the disabling of this feature
image

EditProfileModalComponent and EditProfileGroupModalComponent have been exported from tabby-settings to allow calling the modal from the sidebar.
electron_wxHq3xRT4M

And finally, the search modal has been changed to display the full group path as opposed to only the profile's parent group name.
image

Linked issues #9758 #9210 #411

Introduces support for nested profile groups, allowing groups to have parent groups, icons, and colors. Updates the UI to display groups in a collapsible tree structure, adds icon and color pickers to the group edit modal, and refactors group creation and editing logic to support the new hierarchy.
Re added the ability to set group defaults when creating a group
Moved delete group children to match group collapsed deletion
Moved buildGroupTree to profiles.service to allow for reusability
Groundwork for adding more panels to the app-root
Allows for better targeting than relying on the hierarchy of app-root>.content existing
Introduces a new ProfileTreeComponent with associated template and styles, displaying profile groups and profiles in a collapsible sidebar with filtering and resizing capabilities. Integrates the sidebar into the main app layout and updates module exports to support profile and group editing modals.
@Eugeny
Copy link
Copy Markdown
Owner

Eugeny commented Oct 13, 2025

Thank you so much for the PR!

There are a few layout issues on macOS currently:
image

@Suhun0331
Copy link
Copy Markdown

I think it would be good if this function was added as soon as possible !

@itzhoujun
Copy link
Copy Markdown

nice work

@nisaev
Copy link
Copy Markdown

nisaev commented Nov 26, 2025

nice work. Hope @Eugeny will add it soon.

@nisaev
Copy link
Copy Markdown

nisaev commented Nov 27, 2025

Thank you so much for the PR!

There are a few layout issues on macOS currently: image

margin-top:20px for filter input field should fix it.

@itzhoujun
Copy link
Copy Markdown

Thank you so much for the PR!

There are a few layout issues on macOS currently: image

@D3VL-Jack Hi

@steel97
Copy link
Copy Markdown

steel97 commented Dec 1, 2025

Awesome PR!

@nisaev I think 20px is too close to mac os traffic lights:
img
I suggest using something like margin-top: calc(var(--tabs-height) - 0.5rem). -0.5rem is to compensate p-2 on outer container:
img

Also, I think that this margin should be only applied on macos and only if not in fullscreen mode.
In fullscreen mode on macos it looks weird:
img

I think condition like this may work:

if (process?.platform == 'darwin' && !hostWindow.isFullscreen) {
    // apply margin-top on input here
} else {
    // remove margin-top
}

P.S: I also checked safe-area-inset-top and it doesn't work on electron app unfortunately...

@D3VL-Jack
Copy link
Copy Markdown
Author

Hi all,

Thank you for the positive feedback on this PR!

Unfortunately, I don't have the time nor access to a macOS environment at the moment to work on this small layout issue.

@steel97 thank you for having a look into this already, I hope @Eugeny will be able to use your findings and add this to the PR so it can get merged!

@Jerpy
Copy link
Copy Markdown

Jerpy commented Dec 9, 2025

Awesome PR. Did some testing and it looks like the ellipsis dropdown was removed from managing profiles in profilesSettingsTab.component.pug for duplicating, hide/show, and deletion.

Current release:

Screenshot 2025-12-08 185955

This PR:

Screenshot 2025-12-08 194803

I'm no expert at all but it seems like just reintroducing the section that included the dropdown between lines 68 and 70 fixes this:

.ms-1.hover-reveal(ngbDropdown, placement='bottom-right top-right auto')
	button.btn.btn-link.ms-1(
		ngbDropdownToggle,
		(click)='$event.stopPropagation()'
	)
		i.fas.fa-fw.fa-ellipsis-vertical
	div(ngbDropdownMenu)
		button.dropdown-item(
			ngbDropdownItem,
			(click)='$event.stopPropagation(); newProfile(profile)'
		)
			i.fas.fa-fw.fa-copy
			span(translate) Duplicate

		button.dropdown-item(
			ngbDropdownItem,
			*ngIf='profile.id && !isProfileBlacklisted(profile)',
			(click)='$event.stopPropagation(); blacklistProfile(profile)'
		)
			i.fas.fa-fw.fa-eye-slash
			span(translate) Hide

		button.dropdown-item(
			ngbDropdownItem,
			*ngIf='profile.id && isProfileBlacklisted(profile)',
			(click)='$event.stopPropagation(); unblacklistProfile(profile)'
		)
			i.fas.fa-fw.fa-eye
			span(translate) Show

		button.dropdown-item(
			*ngIf='!profile.isBuiltin',
			(click)='$event.stopPropagation(); deleteProfile(profile)'
		)
			i.fas.fa-fw.fa-trash-alt
			span(translate) Delete

	.ms-1.text-danger.fas.fa-eye-slash(*ngIf='isProfileBlacklisted(profile)')

Screenshot 2025-12-08 193156

So far it seems like the dropdown works. Let me know what you think.

@itzhoujun
Copy link
Copy Markdown

I can't wait to use this feature, can anyone push the progress a bit

@zeroleo12345
Copy link
Copy Markdown

zeroleo12345 commented Dec 30, 2025

at my end, the Listner of document:mouseup made it unable delete/change hotkey when clicked the button in hotkey setting menu.

    @HostListener('document:mouseup')
    stopResize (): void {
        this.panelIsResizing = false
    }

I use below code instead.

# profileTree.component.pug
.grabber(
    cdkDrag,
    cdkDragLockAxis="x",
    (cdkDragStarted)="onDragStarted($event)",
    (cdkDragMoved)="onDragMoved($event)",
    (cdkDragEnded)='onDragEnd($event)',
)

# profileTree.component.ts
    @HostBinding('style.width.px') panelInternalWidth: number = parseInt(window.localStorage.profileTreeWidth ?? 300)

    onDragStarted (event: CdkDragStart) {
        this.panelStartWidth = this.panelInternalWidth
    }

    onDragMoved (event: CdkDragMove) {
        // deltaX
        let width = this.panelStartWidth + event.distance.x
        // min_width < x < max_width
        width = Math.max(this.panelMinWidth, width)
        width = Math.min(this.panelMaxWidth, width)
        this.panelInternalWidth = width
        event.source.setFreeDragPosition({ x: 0, y: 0 })
    }

    onDragEnd (event: CdkDragEnd) {
        window.localStorage.profileTreeWidth = this.panelInternalWidth
    }

Copy link
Copy Markdown

@Coderxrohan Coderxrohan left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is genuinely excellent work !

Huge credit to @D3VL-Jack for taking on a large, non-trivial feature and still keeping backward compatibility intact. Nested groups + a tree-based profile picker is something many users have been asking for over a long time, and this implementation feels well thought out rather than rushed.

I also want to highlight the community effort here —

  1. @steel97 for the detailed macOS layout analysis and practical suggestions
  2. @Jerpy for catching the missing ellipsis dropdown regression and even providing a ready-to-drop fix
  3. @zeroleo12345 for digging into the resize listener issue and proposing a cleaner, state-safe drag-based solution

That kind of collaborative debugging and refinement really shows the strength of this PR.

Yes, there are a few platform-specific and edge-case follow-ups (macOS spacing, small UI regressions), but none of them take away from the core value of this feature. The architecture changes, tree-building logic, and UX improvements are solid and future-proof.

If i want suggest or show something strong contribution, then it will be this.🔥🔥🔥

Overall: strong feature, strong execution, strong collaboration.
Would love to see this land soon...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

9 participants